﻿using System.Linq;
using System.Reflection;
using Autofac;
using MediatR;
using Module = Autofac.Module;

namespace Messhall.Framework.Autofac;

public class AutofacModulesBase : Module
{
    private Assembly _repositoryBaseAssembly;
    private Assembly _repositoryAssembly;
    private Assembly _domainAssembly;
    private Assembly _applicationAssembly;

    public AutofacModulesBase()
    {
    }

    public AutofacModulesBase(Assembly repositoryNamespaceBase, Assembly repositoryNamespace, Assembly domainNamespace,
        Assembly applicationNamespace)
    {
        _repositoryBaseAssembly = repositoryNamespaceBase;
        _repositoryAssembly = repositoryNamespace;
        _domainAssembly = domainNamespace;
        _applicationAssembly = applicationNamespace;
    }

    protected override void Load(ContainerBuilder builder)
    {
        this.AddScansanServices(builder);

        var typeInfos = _domainAssembly.DefinedTypes.Where(t => t.Name.EndsWith("Service")).ToList();

        builder.RegisterAssemblyTypes(_domainAssembly, _repositoryAssembly).Where(t => t.Name.EndsWith("Repository"))
            .AsImplementedInterfaces();
        builder.RegisterAssemblyTypes(_repositoryBaseAssembly, _repositoryAssembly)
            .Where(t => t.Name.EndsWith("ModelCreating")).AsImplementedInterfaces().SingleInstance();
        builder.RegisterAssemblyTypes(_applicationAssembly).Where(t => t.Name.EndsWith("AppService")).SingleInstance();

        builder.RegisterAssemblyTypes(_domainAssembly).Where(t => t.Name.EndsWith("Service")).SingleInstance();
        
        //注入mediaR
        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();

        // Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands
        builder.RegisterAssemblyTypes(_applicationAssembly).AsClosedTypesOf(typeof(IRequestHandler<,>));
        builder.RegisterAssemblyTypes(_applicationAssembly).AsClosedTypesOf(typeof(INotificationHandler<>));
        builder.Register<ServiceFactory>(context =>
        {
            var componentContext = context.Resolve<IComponentContext>();
            return t =>
            {
                object o;
                return componentContext.TryResolve(t, out o) ? o : null;
            };
        });

        base.Load(builder);
    }

    /// <summary>
    /// 自定义扫描扩展
    /// </summary>
    /// <param name="builder"></param>
    protected virtual void AddScansanServices(ContainerBuilder builder)
    {
    }
}